package restless.core.managers {
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.system.System;
	import restless.core.RLEFlashAnimationPoint;
	import restless.core.RLEVisualElement;
	import restless.utilities.numeric.RLEMath;
	
	
	import restless.core.RLEPool;
	import restless.core.gameObjs.RLEBlitMC;
	
	/**
		* @author Jordan Laine
	 */
	
	public class RLEGraphicsManager extends RLEPool {
		
		private var tempMC:MovieClip;
		private var tempSprite:Sprite;
		private var preParse:Array = [];
		private var frames:int;
		private var vGFX:Vector.<Vector.<BitmapData>> = new Vector.<Vector.<BitmapData>>;
		private var nProcessed:int = 0;
		private var nCount:int = 0;
		private var nProcessPerTimerTick:int = 4; //amount of assests that are processed everytime the timer ticks
		private var nTimerInterval:Number = 100; //in MS, 200 = five times a second
		private var timer:Timer;
		private var vFAPs:Vector.<Vector.<RLEFlashAnimationPoint>> = new Vector.<Vector.<RLEFlashAnimationPoint>>;
		private var vFAPID:Vector.<String> = new Vector.<String>;
		private var i:int;
		private var tempBitmap:Bitmap;
		private var tempBitmapData:BitmapData;
		private var _smoothing:Boolean = false;
		
		public function RLEGraphicsManager() {
			super();
		}
		
		public function loadLevelGfx(...arg):void {
			var a:Array = arg;
			i = a.length - 1;
			
			var j:int;
			var f:int;
			var temp:*;
			
			for (i; i > -1; i--) {
				if (a[i] is Array) {
					for (j = a[i].length - 1; j > -1; j--) {	
						if (a[i][j] is Array) {
							for (f = a[i][j].length - 1; f > -1; f--) {
								preParse.push(a[i][j][f]);
							}
						} else {
							preParse.push(a[i][j]);
						}
					}
				} else {
					preParse.push(a[i]);
				}
			}
		}
		
		public function startParse():void {
			nProcessed = 0;
			nCount = 0;
			parseLevelData();
		}
		
		public function startTimerParse():void {
			nProcessed = 0;
			nCount = 0;
			timer = new Timer(nTimerInterval);
		 	timer.addEventListener(TimerEvent.TIMER, parseLevelData);
			timer.start();
		}
		
		protected function parseLevelData(e:Event=null):void {
			i = preParse.length - 1 - nProcessed;
			
			var tempObj:*;
			var tempString:String;
			var vImages:Vector.<BitmapData>;
			
			for (i; i > -1; i--) {
				if (nCount != nProcessPerTimerTick) {
					tempObj = new preParse[i];
					tempString = String(tempObj);
					tempString = tempString.substring(8, tempString.length-1);
					vPoolIDs.push(tempString);
					
					if (tempObj is RLEVisualElement) {
						var tempVE:RLEVisualElement = tempObj;
						vImages = tempVE.parseMC(_smoothing);
						vGFX.push(vImages);
						vFAPID.push(tempString);
						vFAPs.push(tempVE.points);
					} else if (tempObj is MovieClip) {
						vGFX.push( parseMC(tempObj) );
					} else if (tempObj is Sprite) {
						vGFX.push(parseSprite(tempObj) );
					} else if (tempObj is Bitmap) {
						vImages = new Vector.<BitmapData>(1);
						tempBitmapData = tempObj.bitmapData;
						vImages[0] = tempBitmapData;
						vGFX.push(vImages);
					} else if (tempObj is BitmapData) {
						vImages = new Vector.<BitmapData>(1);
						vImages[0] = tempObj;
						vGFX.push(vImages);
					}
					nCount++;
					nProcessed++;
					if (nProcessed >= preParse.length) {
						if (e != null) {
							timer.stop();
							timer = null;
						}
						return;
					}
				} else {
					nCount = 0;
					return;
				}
			}
		}
		
		public function parseMC(mc:MovieClip):Vector.<BitmapData> {
			tempMC = mc;
			frames = tempMC.totalFrames;
			
			var vImages:Vector.<BitmapData> = new Vector.<BitmapData>(frames);
			var i:int = 0;
			for (i; i <= tempMC.totalFrames-1; i++) {
				tempMC.gotoAndStop(i);
				tempBitmapData = new BitmapData(tempMC.width, tempMC.height, true, 0x00000000);
				tempBitmapData.lock();
				tempBitmapData.draw(tempMC, null, null, null, null, _smoothing);
				tempBitmapData.unlock();
				vImages[i] = tempBitmapData;
			}
			return vImages;
		}
		
		public function parseMCWithMatrix(mc:MovieClip, mat:Matrix):Vector.<BitmapData> {
			tempMC = mc;
			var i:int = tempMC.totalFrames;
			var vImages:Vector.<BitmapData> = new Vector.<BitmapData>(frames);
			
			for (i; i > -1; i--) {
				tempMC.gotoAndStop(i + 1);
				tempBitmapData = new BitmapData(tempMC.width, tempMC.height, true, 0x00000000);
				tempBitmapData.lock();
				tempBitmapData.draw(tempMC, mat, null, null, null, _smoothing);
				tempBitmapData.unlock();
				vImages[i] = tempBitmapData;
			}
			return vImages;
		}
		
		public function parseSprite(s:Sprite):Vector.<BitmapData> {
			tempSprite = s;
			var vImages:Vector.<BitmapData> = new Vector.<BitmapData>(1);
			tempBitmapData = new BitmapData(tempSprite.width, tempSprite.height, true, 0x00000000);
			tempBitmapData.lock();
			tempBitmapData.draw(tempSprite, null, null, null, null, _smoothing);
			tempBitmapData.unlock();
			vImages[0] = tempBitmapData;
			return vImages; 
		}
		
		public function removeGFXByName(id:String):void {
			var num:int = vPoolIDs.indexOf(id);
			if (num > -1) {
				vGFX.splice(num, 1);
				vPoolIDs.splice(num, 1);
			}
		}
		
		public function clearPools():void {
			vPoolIDs.length = 0;
			vGFX.length = 0;
		}
		
		public function getPercentParsed():Number {
			var percent:Number = nProcessed / preParse.length;
			if (percent >= 1) {
				preParse.length = 0;
			}
			return int((percent)*100)/100;
		}
		
		public function getMC(id:String):MovieClip {
			i = vPoolIDs.length - 1;
			for (i; i > -1; i--) {
				if (vPoolIDs[i] == id) {
					return new aPoolClasses[i];
				}
			}
			trace("mc not found, try spelling better!");
			return null;
		}
		
		public function set parseTimerInterval(num:Number):void {
			nTimerInterval = num;
		}
		
		public function get parseTimerInterval():Number {
			return nTimerInterval;
		}
		
		public function getFAPs(id:String):Vector.<RLEFlashAnimationPoint> {
			var num:int = vFAPID.indexOf(id);
			return vFAPs[num];
		}
		
		public function getBDV(id:String):Vector.<BitmapData> {
			var num:int = vPoolIDs.indexOf(id);
			return vGFX[num] as Vector.<BitmapData>;
		}
		
		public function set smoothing(bool:Boolean):void {
			_smoothing = bool;
		}
		
		public function get smoothing():Boolean {
			return _smoothing;
		}
		
		override public function dispose():void {
			tempMC = null;
			vPoolIDs = null;
			tempSprite = null;
			preParse = null;
			vGFX = null;
			timer = null;
			
			super.dispose();
		}
	}
}